package com.example.prom.ok.y2022.controller.email.aliyun.handler;

import org.apache.commons.codec.binary.Base64;

import java.io.DataInputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.util.*;

public class AliyunEmailHandler {
    private Boolean authenticate(String method, String uri, Map<String, String> headers) {
        try {
            //获取证书的URL。
            if (!headers.containsKey("x-mns-signing-cert-url")) {
                System.out.println("x-mns-signing-cert-url Header not found");
                return false;
            }
            String cert = headers.get("x-mns-signing-cert-url");
            if (cert.isEmpty()) {
                System.out.println("x-mns-signing-cert-url empty");
                return false;
            }
            cert = new String(Base64.decodeBase64(cert));
            System.out.println("x-mns-signing-cert-url:\t" + cert);

            //根据URL获取证书，并从证书中获取公钥。
            URL url = new URL(cert);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            DataInputStream in = new DataInputStream(conn.getInputStream());
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            Certificate c = cf.generateCertificate(in);
            PublicKey pk = c.getPublicKey();

            //获取待签名字符串。
            String str2sign = getSignStr(method, uri, headers);
            System.out.println("String2Sign:\t" + str2sign);

            //对Authorization字段做Base64解码。
            String signature = headers.get("Authorization");
            byte[] decodedSign = Base64.decodeBase64(signature);

            //认证。
            java.security.Signature signetcheck = java.security.Signature.getInstance("SHA1withRSA");
            signetcheck.initVerify(pk);
            signetcheck.update(str2sign.getBytes());
            Boolean res = signetcheck.verify(decodedSign);
            return res;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    private String getSignStr(String method, String uri, Map<String, String> headers) {
        StringBuilder sb = new StringBuilder();
        sb.append(method);
        sb.append("\n");
        sb.append(safeGetHeader(headers, "Content-md5"));
        sb.append("\n");
        sb.append(safeGetHeader(headers, "Content-Type"));
        sb.append("\n");
        sb.append(safeGetHeader(headers, "Date"));
        sb.append("\n");

        List<String> tmp = new ArrayList<>();
        for (Map.Entry<String, String> entry : headers.entrySet()) {
            if (entry.getKey().startsWith("x-mns-")) {
                tmp.add(entry.getKey() + ":" + entry.getValue());
            }
        }
        Collections.sort(tmp);

        for (String kv : tmp) {
            sb.append(kv);
            sb.append("\n");
        }

        sb.append(uri);
        return sb.toString();
    }

    private String safeGetHeader(Map<String, String> headers, String name) {
        if (headers.containsKey(name)) {
            return headers.get(name);
        } else {
            return "";
        }
    }

    public static void main(String[] args) {
        AliyunEmailHandler sd = new AliyunEmailHandler();
        Map<String, String> headers = new HashMap<>();
        headers.put("Authorization", "IpO/QlkgQarXdhQJ655/0g/R5EA9Gbm1CEX2R4jjkVNZVO0EtIqKBEb7MPE2pusAOLIdIoTf+nBc+XqiJ/PaVQ==");
        headers.put("x-mns-signing-cert-url", "aHR0cHM6Ly9tbnN0ZXN0Lm9zcy1jbi1oYW5nemhvdS5hbGl5dW5jcy5jb20veDUwOV9wdWJsaWNfY2VydGlmaWNhdGUucGVt");
        headers.put("x-mns-version", "2015-06-06");
        headers.put("Date", "Thu, 21 Jul 2022 07:16:02 GMT");
        headers.put("x-mns-request-id", "62D8FD32423430B93C237C22");
        headers.put("Content-md5", "979577E8891A4D029464BFAF900D0FDE");
        headers.put("Content-Type", "text/plain;charset=utf-8");


        headers.put("x-mns-publish-time", "1658387762042");
        headers.put("x-mns-subscription-name", "mns-en-subs-dm-support-1-15915623989891");
        headers.put("x-mns-subscriber", "1559032671635936");
        headers.put("x-mns-topic-name", "mns-en-topics-dm-support-15915623962114");
        headers.put("x-mns-topic-owner", "1559032671635936");
        headers.put("x-mns-message-id", "401AD51F17ED630C7F916A45D77A9217");

        Boolean res = sd.authenticate("POST", "/1c8579a4-8fe2-47f8-a887-0084f65dcbb8", headers);
        System.out.println("Authenticate result:" + res);
    }
}